package com.ctsi.djcloudmqtt.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.ctsi.djcloudmqtt.dto.down.*;
import com.ctsi.djcloudmqtt.dto.down.flighttask_prepare.FlighttaskExecutableConditions;
import com.ctsi.djcloudmqtt.dto.down.flighttask_prepare.FlighttaskPrepareDTO;
import com.ctsi.djcloudmqtt.dto.down.flighttask_prepare.FlighttaskPrepareFile;
import com.ctsi.djcloudmqtt.dto.down.flighttask_prepare.FlighttaskReadyConditions;
import com.ctsi.djcloudmqtt.dto.up.*;
import com.ctsi.djcloudmqtt.enums.CommanderFlightModeEnums;
import com.ctsi.djcloudmqtt.enums.CommanderModeLostActionEnums;
import com.ctsi.djcloudmqtt.enums.DJRthModeEnums;
import com.ctsi.djcloudmqtt.enums.DjMehtodsEnums;
import com.ctsi.djcloudmqtt.mq.MqttSendClient;
import com.ctsi.djcloudmqtt.util.CommonConstants;
import com.ctsi.djcloudmqtt.util.json.jackson.JacksonUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;

@Service
@Slf4j
public class MqttService {

    @Resource
    private MqttSendClient mqttSendClient;

    @Value("${kmz.url}")
    private String kmzUrl;

    @Value("kmz.md5")
    private String kmzMd5;

    /**
     * 线程map
     */
    public static Cache<String, Thread> threadCache = CacheBuilder.newBuilder().expireAfterWrite(5, TimeUnit.SECONDS).build();


    /**
     * 进程map
     */
    public static Cache<String, String> processCache = CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.DAYS).build();

    /**
     * mq返回map
     */
    public static Cache<String, String> jsonCache = CacheBuilder.newBuilder().expireAfterWrite(5, TimeUnit.SECONDS).build();

    @Value("${topicList.thing.product.services}")
    private String thingProductServices;

    @Value("${topicList.gatewaySn}")
    private String gatewaySn;

    public static String gatewaySnKeyWord = "{gateway_sn}";


    /**
     * 一键起飞
     *
     * @return
     */
    public String customTakeoff2point(String bid) {
        if (StrUtil.isEmpty(bid)) {
            bid = UUID.randomUUID().toString();
        }
//        bid = "22222";
        bid = this.flightAuthorityGrab(bid);

        if (StrUtil.isEmpty(bid)) {
            log.info("飞行控制权抢夺失败:" + bid);
            return null;
        }

        log.info("负载控制抢夺权:" + bid);
        bid = this.payloadAuthorityGrab(bid);
        if (StrUtil.isEmpty(bid)) {
            log.info("负载控制抢夺权失败:" + bid);
            return null;
        }

        log.info("一键起飞:" + bid);
        bid = this.takeoff2point(bid);
        if (StrUtil.isEmpty(bid)) {
            log.info("一键起飞失败:" + bid);
            return null;
        }
        processCache.put(bid, "");
        return bid;
    }


    /**
     * 一键起飞
     *
     * @return
     */
    public String takeoff2point(String bid) {

        if (StrUtil.isEmpty(bid)) {
            bid = UUID.randomUUID().toString();
        }

        //发送一键起飞指令
        String topic = thingProductServices.replace(gatewaySnKeyWord, gatewaySn);
        DJParentDTO<TakeoffToPointDownDTO> djParentDTO = new DJParentDTO<>();
        djParentDTO.setTid(UUID.randomUUID().toString());
        djParentDTO.setBid(bid);
        djParentDTO.setTimestamp(System.currentTimeMillis());
        djParentDTO.setMethod(DjMehtodsEnums.TAKEOFF_TO_POINT.getValue());

        TakeoffToPointDownDTO dto = new TakeoffToPointDownDTO();
        dto.setTargetLatitude(32.29);
        dto.setTargetLongitude(120.76);
        dto.setTargetHeight(100);
        dto.setCommanderFlightHeight(80);
        dto.setCommanderModeLostAction(CommanderModeLostActionEnums.JX.getId());
        dto.setRcLostAction(0);
        dto.setFlightId(UUID.randomUUID().toString());
        dto.setMaxSpeed(12);
        dto.setRthAltitude(100);
        dto.setSecurityTakeoffHeight(100);
        dto.setRthMode(DJRthModeEnums.ZNGD.getId());
        dto.setCommanderFlightMode(CommanderFlightModeEnums.ZNGD.getId());
        dto.setExitWaylineWhenRcLost(0);

        djParentDTO.setData(dto);
        this.mqttSendClient.publish(false, topic, Objects.requireNonNull(JacksonUtil.objectToString(djParentDTO)));

        threadCache.put(bid, Thread.currentThread());
        LockSupport.parkUntil(System.currentTimeMillis() + 5 * 1000);
        String result = jsonCache.getIfPresent(bid);
        if (StrUtil.isEmpty(result)) {
            log.info("一键起飞超时:" + bid);
            return null;
        }

        ObjectMapper mapper = new ObjectMapper();
        try {
            DJParentDTO<Takeoff2pointDownDTO> takeoff2pointDownReturnDto = mapper.readValue(result, new TypeReference<DJParentDTO<Takeoff2pointDownDTO>>() {
            });
            if (null == takeoff2pointDownReturnDto || null == takeoff2pointDownReturnDto.getData()) {
                log.info("一键起飞超时转换json错误1:" + bid);
                return null;
            }
            if (0 != takeoff2pointDownReturnDto.getData().getResult()) {
                log.info("一键起飞超时返回错误代码,bid:" + bid, "code:" + takeoff2pointDownReturnDto.getData().getResult());
                return null;
            }
        } catch (JsonProcessingException e) {
            log.info("一键起飞超时转换json错误2:", e);
            return null;
        }
        log.info("一键起飞成功:");
        return bid;
    }

    /**
     * 飞行控制权抢夺
     *
     * @return
     */
    public String flightAuthorityGrab(String bid) {
        if (StrUtil.isEmpty(bid)) {
            bid = UUID.randomUUID().toString();
        }

        String topic = thingProductServices.replace(gatewaySnKeyWord, gatewaySn);
        DJParentDTO<Objects> djParentDTO = new DJParentDTO<>();
        djParentDTO.setTid(UUID.randomUUID().toString());
        djParentDTO.setBid(bid);
        djParentDTO.setTimestamp(System.currentTimeMillis());
        djParentDTO.setMethod(DjMehtodsEnums.FLIGHT_AUTHORITY_GRAB.getValue());

        this.mqttSendClient.publish(false, topic, Objects.requireNonNull(JacksonUtil.objectToString(djParentDTO)));

        log.info("飞行控制权抢夺:" + bid);
        threadCache.put(bid, Thread.currentThread());
        LockSupport.parkUntil(System.currentTimeMillis() + 5 * 1000);

        String result = jsonCache.getIfPresent(bid);
        if (StrUtil.isEmpty(result)) {
            log.info("飞行控制权抢夺超时:" + bid);
            return null;
        }
        ObjectMapper mapper = new ObjectMapper();
        try {
            DJParentDTO<FlightAuthorityGrabDownDTO> flightAuthorityGrabReturnDto = mapper.readValue(result, new TypeReference<DJParentDTO<FlightAuthorityGrabDownDTO>>() {
            });
            if (null == flightAuthorityGrabReturnDto || null == flightAuthorityGrabReturnDto.getData()) {
                log.info("飞行控制权转换json错误1:" + bid);
                return null;
            }
            if (0 != flightAuthorityGrabReturnDto.getData().getResult()) {
                log.info("飞行控制权返回错误代码,bid:" + bid, "code:" + flightAuthorityGrabReturnDto.getData().getResult());
                return null;
            }
        } catch (JsonProcessingException e) {
            log.info("飞行控制权转换json错误2:", e);
            return null;
        }
        log.info("飞行控制权抢夺成功:");
        return bid;
    }


    /**
     * 负载控制抢夺权
     *
     * @return
     */
    public String payloadAuthorityGrab(String bid) {
        if (StrUtil.isEmpty(bid)) {
            bid = UUID.randomUUID().toString();
        }

        String topic = thingProductServices.replace(gatewaySnKeyWord, gatewaySn);

        DJParentDTO<PayloadAuthorityGrabDTO> djParentDTO = new DJParentDTO<>();
        djParentDTO.setTid(UUID.randomUUID().toString());
        djParentDTO.setBid(bid);
        djParentDTO.setTimestamp(System.currentTimeMillis());
        djParentDTO.setMethod(DjMehtodsEnums.PAYLOAD_AUTHORITY_GRAB.getValue());
        djParentDTO.setNeedReply(1);

        PayloadAuthorityGrabDTO payloadAuthorityGrabDTO = new PayloadAuthorityGrabDTO();
        payloadAuthorityGrabDTO.setPayloadIndex("39-0-7");
        djParentDTO.setData(payloadAuthorityGrabDTO);

        this.mqttSendClient.publish(false, topic, Objects.requireNonNull(JacksonUtil.objectToString(djParentDTO)));

        threadCache.put(bid, Thread.currentThread());
        LockSupport.parkUntil(System.currentTimeMillis() + 5 * 1000);

        String result = jsonCache.getIfPresent(bid);
        if (StrUtil.isEmpty(result)) {
            log.info("负载控制抢夺权超时:" + bid);
            return null;
        }
        ObjectMapper mapper = new ObjectMapper();
        try {
            DJParentDTO<PayloadAuthorityGrabDownDTO> payloadAuthorityGrabDownReturnDto = mapper.readValue(result, new TypeReference<DJParentDTO<PayloadAuthorityGrabDownDTO>>() {
            });
            if (null == payloadAuthorityGrabDownReturnDto || null == payloadAuthorityGrabDownReturnDto.getData()) {
                log.info("负载控制抢夺权转换json错误1:" + bid);
                return null;
            }
            if (0 != payloadAuthorityGrabDownReturnDto.getData().getResult()) {
                log.info("负载控制抢夺权返回错误代码,bid:" + bid, "code:" + payloadAuthorityGrabDownReturnDto.getData().getResult());
                return null;
            }
        } catch (JsonProcessingException e) {
            log.info("负载控制抢夺权转换json错误2:", e);
            return null;
        }
        log.info("负载控制抢夺权抢夺成功:");
        return bid;
    }

    /**
     * flyto 飞向目标点
     *
     * @return
     */
    public String fly2point(String bid) {
        if (StrUtil.isEmpty(bid)) {
            bid = UUID.randomUUID().toString();
        }

        String topic = thingProductServices.replace(gatewaySnKeyWord, gatewaySn);

        DJParentDTO<Fly2pointDTO> djParentDTO = new DJParentDTO<>();
        djParentDTO.setTid(UUID.randomUUID().toString());
        djParentDTO.setBid(bid);
        djParentDTO.setTimestamp(System.currentTimeMillis());
        djParentDTO.setMethod(DjMehtodsEnums.PAYLOAD_AUTHORITY_GRAB.getValue());

        Fly2pointDTO fly2pointDTO = new Fly2pointDTO();
        fly2pointDTO.setFly2id(UUID.randomUUID().toString());
        fly2pointDTO.setMaxSpeed(12);



        Fly2pointPointsDTO fly2pointPointsDTO = new Fly2pointPointsDTO();

        fly2pointPointsDTO.setLatitude(32.294300);
        fly2pointPointsDTO.setLongitude(120.768495);
        fly2pointPointsDTO.setHeight(19.0);

        List<Fly2pointPointsDTO> list = new ArrayList<>();
        list.add(fly2pointPointsDTO);
        fly2pointDTO.setPoints(list);

        djParentDTO.setData(fly2pointDTO);

        this.mqttSendClient.publish(false, topic, Objects.requireNonNull(JacksonUtil.objectToString(djParentDTO)));

        threadCache.put(bid, Thread.currentThread());
        LockSupport.parkUntil(System.currentTimeMillis() + 5 * 1000);

        String result = jsonCache.getIfPresent(bid);
        if (StrUtil.isEmpty(result)) {
            log.info("flyto 飞向目标点超时:" + bid);
            return null;
        }
        ObjectMapper mapper = new ObjectMapper();
        try {
            DJParentDTO<Fly2PointDownDTO> fly2PointDownDTO = mapper.readValue(result, new TypeReference<DJParentDTO<Fly2PointDownDTO>>() {
            });
            if (null == fly2PointDownDTO || null == fly2PointDownDTO.getData()) {
                log.info("flyto 飞向目标点转换json错误1:" + bid);
                return null;
            }
            if (0 != fly2PointDownDTO.getData().getResult()) {
                log.info("flyto 飞向目标点返回错误代码,bid:" + bid, "code:" + fly2PointDownDTO.getData().getResult());
                return null;
            }
        } catch (JsonProcessingException e) {
            log.info("flyto 飞向目标点转换json错误2:", e);
            return null;
        }
        log.info("flyto 飞向目标点成功:");
        return bid;
    }

    /**
     * 一键返航
     */
    public String returnHome(String bid) {
        if (StrUtil.isEmpty(bid)) {
            bid = UUID.randomUUID().toString();
        }
        String topic = thingProductServices.replace(gatewaySnKeyWord, gatewaySn);

        DJParentDTO<Objects> djParentDTO = new DJParentDTO<>();
        djParentDTO.setTid(UUID.randomUUID().toString());
        djParentDTO.setBid(bid);
        djParentDTO.setTimestamp(System.currentTimeMillis());
        djParentDTO.setMethod(DjMehtodsEnums.RETURN_HOME.getValue());

        this.mqttSendClient.publish(false, topic, Objects.requireNonNull(JacksonUtil.objectToString(djParentDTO)));

        threadCache.put(bid, Thread.currentThread());
        LockSupport.parkUntil(System.currentTimeMillis() + 5 * 1000);

        String result = jsonCache.getIfPresent(bid);
        if (StrUtil.isEmpty(result)) {
            log.info("flyto 飞向目标点超时:" + bid);
            return null;
        }
        ObjectMapper mapper = new ObjectMapper();
        try {
            DJParentDTO<ReturnHomeDownDTO> returnHomeDownDTO = mapper.readValue(result, new TypeReference<DJParentDTO<ReturnHomeDownDTO>>() {
            });
            if (null == returnHomeDownDTO || null == returnHomeDownDTO.getData()) {
                log.info("一键返航转换json错误1:" + bid);
                return null;
            }
            if (0 != returnHomeDownDTO.getData().getResult()) {
                log.info("一键返航返回错误代码,bid:" + bid, "code:" + returnHomeDownDTO.getData().getResult());
                return null;
            }
        } catch (JsonProcessingException e) {
            log.info("一键返航转换json错误2:", e);
            return null;
        }

        log.info("一键返航成功:");
        return bid;
    }


    /**
     * 下发任务
     * @param bid
     * @param flightId
     * @return
     */
    public String flighttaskPrepare(String bid,String flightId){
        if (StrUtil.isEmpty(bid)) {
            bid = UUID.randomUUID().toString();
        }

        if (StrUtil.isEmpty(flightId)) {
            flightId = UUID.randomUUID().toString();
        }
        String topic = thingProductServices.replace(gatewaySnKeyWord, gatewaySn);

        DJParentDTO<FlighttaskPrepareDTO> djParentDTO = new DJParentDTO<>();
        djParentDTO.setBid(bid);
        djParentDTO.setTid(UUID.randomUUID().toString());
        djParentDTO.setTimestamp(System.currentTimeMillis());
        djParentDTO.setMethod(CommonConstants.DJServiceMethod.FLIGHTTASK_PREPARE);

        FlighttaskPrepareDTO flighttaskPrepareDTO =  new FlighttaskPrepareDTO();
        flighttaskPrepareDTO.setFlightId(flightId);
        flighttaskPrepareDTO.setExecuteTime(System.currentTimeMillis());
        flighttaskPrepareDTO.setTaskType(0);

        FlighttaskPrepareFile flighttaskPrepareFile =  new FlighttaskPrepareFile();
        flighttaskPrepareFile.setUrl(kmzUrl);
        flighttaskPrepareFile.setFingerprint(kmzMd5);
        flighttaskPrepareDTO.setFile(flighttaskPrepareFile);

        FlighttaskReadyConditions flighttaskReadyConditions = new FlighttaskReadyConditions();
        flighttaskReadyConditions.setBatteryCapacity(50);
        flighttaskReadyConditions.setBeginTime(System.currentTimeMillis());
        flighttaskReadyConditions.setEndTime(System.currentTimeMillis() + 24 * 60 * 60 * 1000);
        flighttaskPrepareDTO.setReadyConditions(flighttaskReadyConditions);

        FlighttaskExecutableConditions flighttaskExecutableConditions = new FlighttaskExecutableConditions();
        flighttaskExecutableConditions.setStorageCapacity(1000);
        flighttaskPrepareDTO.setExecutableConditions(flighttaskExecutableConditions);

        flighttaskPrepareDTO.setRthAltitude(100);
        flighttaskPrepareDTO.setRthMode(0);
        flighttaskPrepareDTO.setOutOfControlAction(1);
        flighttaskPrepareDTO.setExitWaylineWhenRcLost(1);
        flighttaskPrepareDTO.setWaylinePrecisionType(1);

        djParentDTO.setData(flighttaskPrepareDTO);

        this.mqttSendClient.publish(false, topic, Objects.requireNonNull(JacksonUtil.objectToString(djParentDTO)));

        threadCache.put(bid, Thread.currentThread());
        LockSupport.parkUntil(System.currentTimeMillis() + 5 * 1000);

        String result = jsonCache.getIfPresent(bid);
        if (StrUtil.isEmpty(result)) {
            log.info("下发任务超时:" + bid);
            return null;
        }
        ObjectMapper mapper = new ObjectMapper();
        try {
            DJParentDTO<ReturnHomeDownDTO> returnHomeDownDTO = mapper.readValue(result, new TypeReference<DJParentDTO<ReturnHomeDownDTO>>() {
            });
            if (null == returnHomeDownDTO || null == returnHomeDownDTO.getData()) {
                log.info("下发任务:" + bid);
                return null;
            }
            if (0 != returnHomeDownDTO.getData().getResult()) {
                log.info("下发任务返回错误代码,bid:" + bid, "code:" + returnHomeDownDTO.getData().getResult());
                return null;
            }
        } catch (JsonProcessingException e) {
            log.info("下发任务转换json错误2:", e);
            return null;
        }
        log.info("下发任务成功:");
        return bid;
    }


    /**
     * 执行任务
     * @param bid
     * @param flightId
     * @return
     */
    public String flighttaskExecute(String bid,String flightId){
        if (StrUtil.isEmpty(bid)) {
            bid = UUID.randomUUID().toString();
        }
        String topic = thingProductServices.replace(gatewaySnKeyWord, gatewaySn);

        DJParentDTO<FlightExecuteDTO> djParentDTO = new DJParentDTO<>();
        djParentDTO.setBid(bid);
        djParentDTO.setTid(UUID.randomUUID().toString());
        djParentDTO.setTimestamp(System.currentTimeMillis());
        djParentDTO.setMethod(CommonConstants.DJServiceMethod.FLIGHTTASK_EXECUTE);

        FlightExecuteDTO flightExecuteDTO = new FlightExecuteDTO();
        flightExecuteDTO.setFlightId(flightId);
        djParentDTO.setData(flightExecuteDTO);

        this.mqttSendClient.publish(false, topic, Objects.requireNonNull(JacksonUtil.objectToString(djParentDTO)));

        threadCache.put(bid, Thread.currentThread());
        LockSupport.parkUntil(System.currentTimeMillis() + 5 * 1000);

        String result = jsonCache.getIfPresent(bid);
        if (StrUtil.isEmpty(result)) {
            log.info("执行任务超时:" + bid);
            return null;
        }
        ObjectMapper mapper = new ObjectMapper();
        try {
            DJParentDTO<ReturnHomeDownDTO> returnHomeDownDTO = mapper.readValue(result, new TypeReference<DJParentDTO<ReturnHomeDownDTO>>() {
            });
            if (null == returnHomeDownDTO || null == returnHomeDownDTO.getData()) {
                log.info("执行任务:" + bid);
                return null;
            }
            if (0 != returnHomeDownDTO.getData().getResult()) {
                log.info("执行任务返回错误代码,bid:" + bid, "code:" + returnHomeDownDTO.getData().getResult());
                return null;
            }
        } catch (JsonProcessingException e) {
            log.info("执行任务转换json错误2:", e);
            return null;
        }
        log.info("执行任务成功:");
        return bid;
    }


    /**
     * 取消任务
     * @param bid
     * @param flightIds
     * @return
     */
    public String flighttaskUndo(String bid,List<String> flightIds){
        if (StrUtil.isEmpty(bid)) {
            bid = UUID.randomUUID().toString();
        }
        if(CollectionUtil.isEmpty(flightIds)){
            log.info("取消任务id为空:" + flightIds);
            return null;
        }
        String topic = thingProductServices.replace(gatewaySnKeyWord, gatewaySn);

        DJParentDTO<FlightUndoDTO> djParentDTO = new DJParentDTO<>();
        djParentDTO.setBid(bid);
        djParentDTO.setTid(UUID.randomUUID().toString());
        djParentDTO.setTimestamp(System.currentTimeMillis());
        djParentDTO.setMethod(CommonConstants.DJServiceMethod.FLIGHTTASK_UNDO);

        FlightUndoDTO flightUndoDTO = new FlightUndoDTO();
        flightUndoDTO.setFlightIds(flightIds);
        djParentDTO.setData(flightUndoDTO);

        this.mqttSendClient.publish(false, topic, Objects.requireNonNull(JacksonUtil.objectToString(djParentDTO)));

        threadCache.put(bid, Thread.currentThread());
        LockSupport.parkUntil(System.currentTimeMillis() + 5 * 1000);

        String result = jsonCache.getIfPresent(bid);
        if (StrUtil.isEmpty(result)) {
            log.info("取消任务超时:" + bid);
            return null;
        }
        ObjectMapper mapper = new ObjectMapper();
        try {
            DJParentDTO<ReturnHomeDownDTO> returnHomeDownDTO = mapper.readValue(result, new TypeReference<DJParentDTO<ReturnHomeDownDTO>>() {
            });
            if (null == returnHomeDownDTO || null == returnHomeDownDTO.getData()) {
                log.info("取消任务:" + bid);
                return null;
            }
            if (0 != returnHomeDownDTO.getData().getResult()) {
                log.info("取消任务返回错误代码,bid:" + bid, "code:" + returnHomeDownDTO.getData().getResult());
                return null;
            }
        } catch (JsonProcessingException e) {
            log.info("取消任务转换json错误2:", e);
            return null;

        }
        log.info("取消任务成功:");
        return bid;
    }


    /**
     * 航线暂停
     * @return
     */
    public String flighttaskPause(String bid){
        if (StrUtil.isEmpty(bid)) {
            bid = UUID.randomUUID().toString();
        }

        String topic = thingProductServices.replace(gatewaySnKeyWord, gatewaySn);

        DJParentDTO<?> djParentDTO = new DJParentDTO<>();
        djParentDTO.setBid(bid);
        djParentDTO.setTid(UUID.randomUUID().toString());
        djParentDTO.setTimestamp(System.currentTimeMillis());
        djParentDTO.setMethod(CommonConstants.DJServiceMethod.FLIGHTTASK_PAUSE);

        this.mqttSendClient.publish(false, topic, Objects.requireNonNull(JacksonUtil.objectToString(djParentDTO)));

        threadCache.put(bid, Thread.currentThread());
        LockSupport.parkUntil(System.currentTimeMillis() + 5 * 1000);

        String result = jsonCache.getIfPresent(bid);
        if (StrUtil.isEmpty(result)) {
            log.info("航线暂停超时:" + bid);
            return null;
        }
        ObjectMapper mapper = new ObjectMapper();
        try {
            DJParentDTO<ReturnHomeDownDTO> returnHomeDownDTO = mapper.readValue(result, new TypeReference<DJParentDTO<ReturnHomeDownDTO>>() {
            });
            if (null == returnHomeDownDTO || null == returnHomeDownDTO.getData()) {
                log.info("航线暂停:" + bid);
                return null;
            }
            if (0 != returnHomeDownDTO.getData().getResult()) {
                log.info("航线暂停返回错误代码,bid:" + bid, "code:" + returnHomeDownDTO.getData().getResult());
                return null;
            }
        } catch (JsonProcessingException e) {
            log.info("航线暂停转换json错误2:", e);
            return null;
        }
        log.info("航线暂停成功:");
        return bid;
    }


    /**
     * 航线恢复
     * @return
     */
    public String flighttaskRecovery(String bid){
        if (StrUtil.isEmpty(bid)) {
            bid = UUID.randomUUID().toString();
        }

        String topic = thingProductServices.replace(gatewaySnKeyWord, gatewaySn);

        DJParentDTO<?> djParentDTO = new DJParentDTO<>();
        djParentDTO.setBid(bid);
        djParentDTO.setTid(UUID.randomUUID().toString());
        djParentDTO.setTimestamp(System.currentTimeMillis());
        djParentDTO.setMethod(CommonConstants.DJServiceMethod.FLIGHTTASK_RECOVERY);

        this.mqttSendClient.publish(false, topic, Objects.requireNonNull(JacksonUtil.objectToString(djParentDTO)));

        threadCache.put(bid, Thread.currentThread());
        LockSupport.parkUntil(System.currentTimeMillis() + 5 * 1000);

        String result = jsonCache.getIfPresent(bid);
        if (StrUtil.isEmpty(result)) {
            log.info("航线恢复超时:" + bid);
            return null;
        }
        ObjectMapper mapper = new ObjectMapper();
        try {
            DJParentDTO<ReturnHomeDownDTO> returnHomeDownDTO = mapper.readValue(result, new TypeReference<DJParentDTO<ReturnHomeDownDTO>>() {
            });
            if (null == returnHomeDownDTO || null == returnHomeDownDTO.getData()) {
                log.info("航线恢复:" + bid);
                return null;
            }
            if (0 != returnHomeDownDTO.getData().getResult()) {
                log.info("航线恢复返回错误代码,bid:" + bid, "code:" + returnHomeDownDTO.getData().getResult());
                return null;
            }
        } catch (JsonProcessingException e) {
            log.info("航线恢复转换json错误2:", e);
            return null;
        }
        log.info("航线恢复成功:");
        return bid;
    }


    /**
     * 任务资源获取
     * @return
     */
    public ReturnHomeDownWithDataDTO<FlighttaskResourceGetReturnHomeDownDTO> flighttaskResourceGet(){

        String bid = UUID.randomUUID().toString();

        String topic = thingProductServices.replace(gatewaySnKeyWord, gatewaySn);

        DJParentDTO<?> djParentDTO = new DJParentDTO<>();
        djParentDTO.setBid(bid);
        djParentDTO.setTid(UUID.randomUUID().toString());
        djParentDTO.setTimestamp(System.currentTimeMillis());
        djParentDTO.setMethod(CommonConstants.DJServiceMethod.FLIGHTTASK_RESOURCE_GET);

        this.mqttSendClient.publish(false, topic, Objects.requireNonNull(JacksonUtil.objectToString(djParentDTO)));

        threadCache.put(bid, Thread.currentThread());
        LockSupport.parkUntil(System.currentTimeMillis() + 5 * 1000);

        String result = jsonCache.getIfPresent(bid);
        if (StrUtil.isEmpty(result)) {
            log.info("任务资源获取超时:" + bid);
            return null;
        }
        ObjectMapper mapper = new ObjectMapper();
        DJParentDTO<ReturnHomeDownWithDataDTO<FlighttaskResourceGetReturnHomeDownDTO>> returnHomeDownDTO;
        try {
            returnHomeDownDTO =   mapper.readValue(result, new TypeReference<DJParentDTO<ReturnHomeDownWithDataDTO<FlighttaskResourceGetReturnHomeDownDTO>>>() {
            });
            if (null == returnHomeDownDTO || null == returnHomeDownDTO.getData()) {
                log.info("任务资源获取:" + bid);
                return null;
            }
            if (0 != returnHomeDownDTO.getData().getResult()) {
                log.info("任务资源获取返回错误代码,bid:" + bid, "code:" + returnHomeDownDTO.getData().getResult());
                return null;
            }
        } catch (JsonProcessingException e) {
            log.info("任务资源获取转换json错误2:", e);
            return null;
        }
        log.info("任务资源获取成功:");
        return returnHomeDownDTO.getData();
    }


    public Takeoff2PointProgressUpDTO takeoff2pointProgress(String bid){
        if(StrUtil.isEmpty(bid)){
            bid = UUID.randomUUID().toString();
        }
        ObjectMapper mapper = new ObjectMapper();
        log.info("查询无人机一键起飞状态");
        String takeoff2PointProgressJson = MqttService.processCache.getIfPresent(bid+ CommonConstants.DJServiceMethod.TAKEOFF_2_POINT_PROGRESS);
        try {
            Takeoff2PointProgressUpDTO takeoff2PointProgressUpDTO = mapper.readValue(takeoff2PointProgressJson, new TypeReference<Takeoff2PointProgressUpDTO>() {
            });
            if (null == takeoff2PointProgressUpDTO) {
                log.info("获取一键起飞状态转换json错误1:" + bid);
                return null;
            }
            return takeoff2PointProgressUpDTO;
        } catch (JsonProcessingException e) {
            log.info("获取一键起飞状态文本转换json错误2:", e);
            return null;
        }
    }

    /**
     * psdk-发送文本框内容
     */
    public String speakerTtsPlayStart(String bid) {
        if (StrUtil.isEmpty(bid)) {
            bid = UUID.randomUUID().toString();
        }

        ObjectMapper mapper = new ObjectMapper();


        log.info("查询无人机flyto 执行结果事件通知状态");
        String fly2PointProgressJson = MqttService.processCache.getIfPresent(bid+ CommonConstants.DJServiceMethod.FLY_2_POINT_PROGRESS);
        try {
            Fly2PointProgressUpDTO fly2PointProgressUpDTO = mapper.readValue(fly2PointProgressJson, new TypeReference<Fly2PointProgressUpDTO>() {
            });
            if (null == fly2PointProgressUpDTO) {
                log.info("获取无人机flyto 执行结果事件json错误1:" + bid);
                return null;
            }
            if (!fly2PointProgressUpDTO.getStatus().equals("wayline_ok")) {
                log.info("获取无人机flyto 执行结果事件未完成" + bid);
                return null;
            }
        } catch (JsonProcessingException e) {
            log.info("获取无人机flyto 执行结果事件转换json错误2:", e);
            return null;
        }

        log.info("查询无人机喊话器-tts播放进度通知状态");
        String speakerTtsPlayStartProgressJson = MqttService.processCache.getIfPresent(bid+ CommonConstants.DJServiceMethod.SPEAKER_TTS_PLAY_START_PROGRESS);
        try {
            SpeakerAudioPlayStartProgressUpDTO speakerAudioPlayStartProgressUpDTO = mapper.readValue(speakerTtsPlayStartProgressJson, new TypeReference<SpeakerAudioPlayStartProgressUpDTO>() {
            });
            if (null == speakerAudioPlayStartProgressUpDTO) {
                log.info("查询无人机喊话器-tts播放进度通知json错误1:" + bid);
                return null;
            }
            if (!speakerAudioPlayStartProgressUpDTO.getOutput().getStatus().equals("ok")) {
                log.info("查询无人机喊话器-tts播放进度通知未完成" + bid);
                return null;
            }
        } catch (JsonProcessingException e) {
            log.info("查询无人机喊话器-tts播放进度通知错误2:", e);
            return null;
        }

        log.info("设置播放模式为循环播放");
        bid = this.speakerPlayModeSet(bid);
        if (StrUtil.isEmpty(bid)) {
            log.info("喊话器-设置播放模式失败:" + bid);
            return null;
        }


        String topic = thingProductServices.replace(gatewaySnKeyWord, gatewaySn);

        DJParentDTO<SpeakerTtsPlayStartDTO> djParentDTO = new DJParentDTO<>();
        djParentDTO.setTid(UUID.randomUUID().toString());
        djParentDTO.setBid(bid);
        djParentDTO.setTimestamp(System.currentTimeMillis());
        djParentDTO.setMethod(DjMehtodsEnums.SPEAKER_TTS_PLAY_START.getValue());

        SpeakerTtsPlayStartDTO speakerTtsPlayStartDTO = new SpeakerTtsPlayStartDTO();
        speakerTtsPlayStartDTO.setPsdkIndex(2);

        SpeakerTtsPlayStartTTSDTO speakerTtsPlayStartTTSDTO = new SpeakerTtsPlayStartTTSDTO();
        speakerTtsPlayStartTTSDTO.setMd5(SecureUtil.md5("1111"));
        speakerTtsPlayStartTTSDTO.setText("1111");
        speakerTtsPlayStartTTSDTO.setName("1111");
        speakerTtsPlayStartDTO.setTts(speakerTtsPlayStartTTSDTO);

        djParentDTO.setData(speakerTtsPlayStartDTO);

        this.mqttSendClient.publish(false, topic, Objects.requireNonNull(JacksonUtil.objectToString(djParentDTO)));

        threadCache.put(bid, Thread.currentThread());
        LockSupport.parkUntil(System.currentTimeMillis() + 5 * 1000);

        String result = jsonCache.getIfPresent(bid);
        if (StrUtil.isEmpty(result)) {
            log.info("喊话器-开始播放TTS文本超时:" + bid);
            return null;
        }


        try {
            DJParentDTO<SpeakerTtsPlayStartDownDTO> speakerTtsPlayStartDownDTO = mapper.readValue(result, new TypeReference<DJParentDTO<SpeakerTtsPlayStartDownDTO>>() {
            });
            if (null == speakerTtsPlayStartDownDTO || null == speakerTtsPlayStartDownDTO.getData()) {
                log.info("喊话器-开始播放TTS文本转换json错误1:" + bid);
                return null;
            }
            if (0 != speakerTtsPlayStartDownDTO.getData().getResult()) {
                log.info("喊话器-开始播放TTS文本返回错误代码,bid:" + bid, "code:" + speakerTtsPlayStartDownDTO.getData().getResult());
                return null;
            }
        } catch (JsonProcessingException e) {
            log.info("喊话器-开始播放TTS文本转换json错误2:", e);
            return null;
        }
        log.info("喊话器-开始播放TTS文本成功:");
        return bid;
    }


    /**
     * 喊话器-设置播放模式
     */
    public String speakerPlayModeSet(String bid){

        DJParentDTO<SpeakerPlayModeSetDwonDTO> djParentDTO = new DJParentDTO<>();
        djParentDTO.setTid(UUID.randomUUID().toString());
        djParentDTO.setBid(bid);
        djParentDTO.setTimestamp(System.currentTimeMillis());
        djParentDTO.setMethod(DjMehtodsEnums.SPEAKER_PLAY_MODE_SET.getValue());

        SpeakerPlayModeSetDwonDTO speakerPlayModeSetDwonDTO = new SpeakerPlayModeSetDwonDTO();
        speakerPlayModeSetDwonDTO.setPlayMode(1);
        speakerPlayModeSetDwonDTO.setPsdkIndex(0);
        djParentDTO.setData(speakerPlayModeSetDwonDTO);

        String topic = thingProductServices.replace(gatewaySnKeyWord, gatewaySn);

        this.mqttSendClient.publish(false, topic, Objects.requireNonNull(JacksonUtil.objectToString(djParentDTO)));

        threadCache.put(bid, Thread.currentThread());
        LockSupport.parkUntil(System.currentTimeMillis() + 5 * 1000);

        String result = jsonCache.getIfPresent(bid);
        if (StrUtil.isEmpty(result)) {
            log.info("喊话器-设置播放模式超时:" + bid);
            return null;
        }
        ObjectMapper mapper = new ObjectMapper();
        try {
            DJParentDTO<SpeakerPlayModeSetUpDTO> speakerPlayModeSetUpDTODTO = mapper.readValue(result, new TypeReference<DJParentDTO<SpeakerPlayModeSetUpDTO>>() {
            });
            if (null == speakerPlayModeSetUpDTODTO || null == speakerPlayModeSetUpDTODTO.getData()) {
                log.info("喊话器-设置播放模式转换json错误1:" + bid);
                return null;
            }
            if (0 != speakerPlayModeSetUpDTODTO.getData().getResult()) {
                log.info("喊话器-设置播放模式返回错误代码,bid:" + bid, "code:" + speakerPlayModeSetUpDTODTO.getData().getResult());
                return null;
            }
        } catch (JsonProcessingException e) {
            log.info("喊话器-设置播放模式转换json错误2:", e);
            return null;
        }
        log.info("喊话器-设置播放模式成功:");
        return bid;
    }


    /**
     * 喊话器-停止播放
     */
    public String speakerPlayStop(String bid){

        DJParentDTO<SpeakerPlayStopDownDTO> djParentDTO = new DJParentDTO<>();
        djParentDTO.setTid(UUID.randomUUID().toString());
        djParentDTO.setBid(bid);
        djParentDTO.setTimestamp(System.currentTimeMillis());
        djParentDTO.setMethod(DjMehtodsEnums.SPEAKER_PLAY_MODE_SET.getValue());

        SpeakerPlayStopDownDTO speakerPlayStopDownDTO = new SpeakerPlayStopDownDTO();
        speakerPlayStopDownDTO.setPsdkIndex(0);
        djParentDTO.setData(speakerPlayStopDownDTO);

        String topic = thingProductServices.replace(gatewaySnKeyWord, gatewaySn);

        this.mqttSendClient.publish(false, topic, Objects.requireNonNull(JacksonUtil.objectToString(djParentDTO)));

        threadCache.put(bid, Thread.currentThread());
        LockSupport.parkUntil(System.currentTimeMillis() + 5 * 1000);

        String result = jsonCache.getIfPresent(bid);
        if (StrUtil.isEmpty(result)) {
            log.info("喊话器-停止播放超时:" + bid);
            return null;
        }
        ObjectMapper mapper = new ObjectMapper();
        try {
            DJParentDTO<SpeakerPlayStopUpDTO> speakerPlayModeSetUpDTODTO = mapper.readValue(result, new TypeReference<DJParentDTO<SpeakerPlayStopUpDTO>>() {
            });
            if (null == speakerPlayModeSetUpDTODTO || null == speakerPlayModeSetUpDTODTO.getData()) {
                log.info("喊话器-停止播放转换json错误1:" + bid);
                return null;
            }
            if (0 != speakerPlayModeSetUpDTODTO.getData().getResult()) {
                log.info("喊话器-停止播放返回错误代码,bid:" + bid, "code:" + speakerPlayModeSetUpDTODTO.getData().getResult());
                return null;
            }
        } catch (JsonProcessingException e) {
            log.info("喊话器-停止播放转换json错误2:", e);
            return null;
        }
        log.info("喊话器-停止播放成功:");
        return bid;
    }



}
